1 Flex 入門


この章では字句スキャン処理の概念を紹介し、Flex のようなツールの必要性を指摘します。この章の後半部分で Flex を紹介し、Flex を使うことのできる状況の実例をいくつか紹介します。

UNIX および C の世界では、ファイルは通常個々のバイトが連続したものとして扱われます。個々のバイトを集めてどのようにグループ化するかという点は、プログラマが決めることです。このような抽象化は非常に強力です。というのは、どのようなファイルであってもこれによって表現することができるからです。しかしそこには短所もあって、プログラマはほとんど常に生のファイルに対して構造をあてはめなければなりません。これは言葉を変えると、ファイルをより意味のある部分に分割しなければならないということです。例えば、コンパイラのある部分はファイルから連続した文字を受け取り、構文チェッカが理解することのできる構成要素、例えば、数値、キーワード、文字列などにグループ化します。このようなことを行う理由は、コンパイラの言語パーサが処理を行うのは連続した文字に対してではなく、その言語のシンボルが連続したものに対してだからです。

データベース・アプリケーションやバイナリ・ファイルを扱うアプリケーションは、扱うデータに対してある固定されたフォーマットというものを持っていることが多く、そのフォーマットを使って入力データから意味を導き出します。テキストを入力するプログラムは通常これとは反対で、このようなプログラムは入力を単語やシンボルに分割しなければならないことが多いのですが、通常これらの単語やシンボルがどのように配置されているかを示す決まった構造というものは存在しません。したがって、入力された情報を意味のあるシンボルに分割するために、テキスト処理を行うプログラムは字句解析もしくは字句スキャンと呼ばれる処理を行う部分を持っていることが多く、そこで入力情報の分割が行われます。このようなことを行う関数群のことを字句アナライザもしくは字句スキャナ、あるいは短く「スキャナ」と呼びます。

一般的にスキャナを作成するのは、プログラマにとって難しいことでも面白いことでもないのですが、時間のかかる作業になることはあります。ほとんどのポピュラーなプログラミング言語はスキャナの作成を支援する機能をほとんど提供していません。というのは、これらのプログラミング言語は連続した文字を単語、トークン、シンボルに分割する組み込みの機能を持っていないからです。通常はこのような仕事を行うライブラリ・ルーチンが存在しますが、これらは柔軟でなかったり、使いにくいものであったり、あるいは、それらのルーチンとのやりとりにあまりに多くのコードが必要になったりすることが多いために、実装上の細かな点によって根本的な問題が不明瞭にされてしまいます。

1つの良い例が、C 言語で許されているすべての数値型(浮動小数、10 進整数、16 進整数、8 進整数)を処理するスキャナを C 言語で記述する場合です。これは非常に難しいということはありませんが、出来上がったコードは通常美しいとはとても言えないものでしょうし、その保守や拡張は容易でないことが多いのです。

ほとんどのプログラマが性急に主張するように、他人の書いたコードを保守するのは通常あまり楽しい作業ではありません。さらに、美しくないコードを保守するのは、楽しいというにはほど遠いものです。こうして、スキャナを書くことが退屈で、その保守が難しいとすると、スキャナの作成をより容易にしてくれる方法を考えようとするに足る理由のあったことが読者にもお分かりいただけるでしょう。

1.1 問題解決手段としての Flex

ここで Flex が登場することになります。Flex はプログラマに対して、字句解析処理部分をきれいに記述し、その記述にしたがった効率的な字句スキャナを生成する方法を提供します。プログラマは Flex に対して、必要なスキャナに関する記述情報を提供します。Flex はその記述情報を使って C 言語で書かれたスキャナを生成します。記述に使われる言語は上級言語であり、スキャナの記述に関しては C 言語よりもはるかに適しています。それを使うことでプログラマは、文字をどのようにグループ化し、グループ化が完了した時にどのようなアクションを発生させるかを指定することができます。

注:このマニュアルのほとんどの部分は Flex、Lex の両方を対象にしています。Lex は(Flex には劣りますが) ほとんどの UNIX システム上にある標準のスキャナ生成ユーティリティです。両者の間に違いがある場合には、Flex を優先させています。Lex については***ページの 8.2 節「標準 Lex」で簡単に説明してあります。

ここでも1つの良い例がコンパイラです。前に議論したように、コンパイラの構文チェッカは、文字が連続したものではなく、言語文法の構成要素を表すトークンが連続したものを入力として受け取る必要があります。Flex はこのような場合に最適です。Flex によって生成されたスキャナが構文チェッカとファイルの仲介役となり、構文チェッカが次の有意味なトークンを要求するのを待ちます。Flex はファイルを読み、プログラマによって与えられた記述にしたがって文字をグループ化して、マッチしたトークンを返却します。この処理は、スキャナもしくはパーサが終了するまで続きます。

C のコンパイラを作成する場合、このようなことを行うために必要となる Flex の記述情報はコードの行数にして 100 行から 300 行くらいになるかもしれません。この記述情報のほとんどは、シンボル・テーブルの管理、識別子の検索、型のマッピング、ある数の値等の追加情報の返却を行うための補助的な C コードになるでしょう。これら自体は記述情報の一部ではありませんが、通常、コンパイラによって必要とされるものです。

概念的には Flex は、原材料(文字)を取り込み、消費者(パーサ等)がすぐに使うことができる最終製品(トークン)を製造する工場のようなものです。

1.2 一般的なプログラミング・ツールとしての Flex

Flex はコンパイラにしか使えないということはありません。読者のコンピュータ上にある、ファイルを読み込んだり、何等かの形で文字のグループを処理する必要のあるすべてのプログラム、特に、変換フィルタや言語ツールのことを考えてみてください。これらのプログラムのほとんどすべてが Flex 単体、もしくは Flex と他のツールの組み合わせによって作成することができます。

1つの良い例が文字数のカウントです。例えば、ファイルの中の全行数、個々の文字の出現回数、foo という単語の出現回数を調べるプログラムを作成したいとしましょう。これは標準的なツール(grep、sed、awk、perl、その他)で作成することも C 言語のプログラムを書いて作成することもできますが、Flex で作成することもできます。他の例として、特定のキーワードを探す必要のある、メール・リーダがあります。ここでも、それを標準ツールで実現することも、Flex と C 言語で実現することもできます。

Flex を使うことでプログラマは、スキャナの開発やファイルを構成する文字の処理にかかる時間を大幅に減らすことができます。ほとんどの場合、Flex に対する入力情報は、既存のプログラミング言語で記述されたコードと比較して、より理解しやすく、少なくとも同じ程度の移植性があり、保守もより簡単です。それだけでなく、Flex でスキャナを開発するのにかかる時間は、既存のプログラミング言語で同等のスキャナを開発する場合と比較してきわめて短くてすむので、Flex はプロトタイピングや、一度しか使わないプログラムやフィルタの開発に最適です。


Copyright (C) 1992, 1993 Free Software Foundation

Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.

Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.

Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions, except that this permission notice may be stated in a translation approved by the Free Software Foundation.


日本語訳:市川和久
Japanese translation by Kazuhisa Ichikawa (ki@home.email.ne.jp)